home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / FLAT.ZIP / MEMMAN.C < prev    next >
C/C++ Source or Header  |  1993-06-13  |  20KB  |  652 lines

  1. /**********************************************************************
  2. ** Program:    Memory Manager
  3. ** File:       memman.c
  4. ** Model:      medium
  5. ** Windows:    3.x
  6. ** Version:    1.0
  7. ** Author:     hb
  8. ** Date:       04/10/93
  9. ** Functions:  CreateHeap       creates a static heap. Only one allowed!
  10. **             DestroyHeap      destroys the heap
  11. **            *AllocMemMan         allocates a piece of memory in the heap
  12. **            *ReAllocMem       tries to grow an allocated piece of memory
  13. **             FreeMem          frees a piece of memory
  14. ** internal functions:
  15. **             GetOffset        calculates the offset in the heap for a pointer
  16. **            *GetPointer       calculates a pointer from a heapoffset
  17. **             GetHeapIndex     returns the index of a heapnode in the heaplist
  18. **             GetFreeIndex     returns the index of a freenode in the freenodelist
  19. **             GetFreeHeapIndex returns the next unused index in the heaplist
  20. **             GetFreeFreeIndex returns the next unused index in the freenodelist
  21. **             MeltFreeList     tries to merge adjacent nodes in the freenodelist
  22. **             SortFreeNodes    Quicksort for the freenodelist
  23. ***************************************************************************/
  24.  
  25.  
  26. /* Make sure it works for ALL Windows 3.x version */
  27. #define WIN30
  28. /* For Borland's 'Chiseled Gray' background */
  29. #define HAS_BWCC
  30. /* For StratosWare MemCheck routines */
  31. #define HAS_MEMCHECK
  32.  
  33. /******* Includes ********/
  34. #include <windows.h>
  35. #ifdef HAS_BWCC
  36. #include <bwcc.h>
  37. #endif
  38. #define MAINMEM
  39. #include "\borlandc\winmem\memman.h"
  40. #ifdef HAS_MEMCHECK
  41. #include "\wmemchec\memcheck.h"
  42. #endif
  43.  
  44. /***CreateHeap*********************************************************
  45. ** Program:    Memory Manager
  46. ** File:       Memman.c
  47. ** Funktion:   CreateHeap creates a heap
  48. **             - does not create a heap in realmode
  49. **             - creates only one heap because all handles stored in global vars.
  50. **             - create a freenodelist and a heapnodelist with fixed number of entries
  51. **             - heap, freenode and heapnodes are locked until destroyheap is called
  52. ** Return:     error
  53. ** Author:     hb
  54. ** Date:       12.6.92
  55. ****************************************************************************/
  56. int CreateHeap (long lSize, int nMaxNodes)
  57. {
  58.    DWORD           dwInfo,
  59.                    dwListSize;
  60.    long            l;
  61.  
  62. /* is there already a heap? **/
  63.      if (hHeap != NULL) {
  64.        ShowMemoryError(IDE_ONLYONEHEAP);
  65.         return (IDE_ONLYONEHEAP);
  66.    }
  67. /* get mode info **/
  68.    dwInfo = GetWinFlags();
  69. /* calculate segment boundaries **/
  70.    if (dwInfo & WF_ENHANCED)
  71.       lSegBorder = 0L;
  72.    else if (dwInfo & WF_STANDARD)
  73.       lSegBorder = 17L;
  74.    else {
  75.          ShowMemoryError(IDE_REALMODE);
  76.          return (IDE_REALMODE);
  77.    }
  78. /* try to allocate room for the heapnodes in global memory **/
  79.    dwListSize = sizeof (struct node);
  80.    dwListSize *= nMaxNodes;
  81.    hHeapNodes = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwListSize);
  82.    if (hHeapNodes == NULL) {
  83.          ShowMemoryError(IDE_NOMEMAVAIL);
  84.          return (IDE_NOMEMAVAIL);
  85.    }
  86. /* try to allocate room for the freenodes in global memory **/
  87.    hFreeNodes = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwListSize);
  88.    if (hFreeNodes == NULL)
  89.    {
  90.       GlobalFree (hHeapNodes);
  91.       hHeapNodes = NULL;
  92.             ShowMemoryError(IDE_NOMEMAVAIL);
  93.             return (IDE_NOMEMAVAIL);
  94.    }
  95. /* try to allocate room for the heap in global memory **/
  96.    hHeap = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, lSize);
  97.    if (hHeap == NULL)
  98.    {
  99.       GlobalFree (hHeapNodes);
  100.       GlobalFree (hFreeNodes);
  101.       hHeapNodes = NULL;
  102.       hFreeNodes = NULL;
  103.             ShowMemoryError(IDE_NOMEMAVAIL);
  104.             return (IDE_NOMEMAVAIL);
  105.    }
  106. /* lock all handles to get basepointers */
  107.    HeapNodes = (LPNODE) GlobalLock (hHeapNodes);
  108.    FreeNodes = (LPNODE) GlobalLock (hFreeNodes);
  109.    if (HeapNodes == NULL || FreeNodes == NULL)
  110.    {
  111.       GlobalUnlock (hHeapNodes);
  112.       GlobalUnlock (hFreeNodes);
  113.       GlobalFree (hHeapNodes);
  114.       GlobalFree (hFreeNodes);
  115.       hHeapNodes = NULL;
  116.       hFreeNodes = NULL;
  117.             ShowMemoryError(IDE_MEMERROR);
  118.             return (IDE_MEMERROR);
  119.    }
  120. /* calculate real size of heap **/
  121.    lHeapSize = GlobalSize (hHeap);
  122.    hpBase = (char huge *) GlobalLock (hHeap);
  123.    if (hpBase == NULL)
  124.    {
  125.       GlobalFree (hHeap);
  126.       hHeap = NULL;
  127.             ShowMemoryError(IDE_MEMERROR);
  128.             return (IDE_MEMERROR);
  129.    }
  130. /* create the startup entries in freenodes, one entry per segment **/
  131.    for (l=0L,nFreeUsed=0;l<lHeapSize;nFreeUsed++,l+=SEGMENT)
  132.    {
  133.       FreeNodes[nFreeUsed].lOffset = (long) nFreeUsed * SEGMENT;
  134.       if ((lHeapSize - l) / SEGMENT > 0L)
  135.          FreeNodes[nFreeUsed].lSize = SEGMENT - lSegBorder;
  136.       else
  137.          FreeNodes[nFreeUsed].lSize = lHeapSize - ((long) nFreeUsed * SEGMENT);
  138.    }
  139.    nHeapUsed = 0;
  140.    nNodes = nMaxNodes;
  141.    return (IDE_OK);
  142. }
  143.  
  144. /***DestroyHeap********************************************************
  145. ** Program:    Memory Manager
  146. ** File:       Memman.c
  147. ** Funktion:   DestroyHeap destroys the heap
  148. ** Return:     error
  149. ** Author:     hb
  150. ** Date:       12.6.92
  151. ****************************************************************************/
  152. int DestroyHeap (void)
  153. {
  154.  
  155. /* is ther a heap ? **/
  156.    if (hHeap == NULL)
  157.       return (IDE_NOHEAP);
  158. /* free nodelists and heap */
  159.    GlobalUnlock (hHeapNodes);
  160.    GlobalUnlock (hFreeNodes);
  161.    GlobalFree (hHeapNodes);
  162.    GlobalFree (hFreeNodes);
  163.    hHeapNodes = NULL;
  164.    hFreeNodes = NULL;
  165.    GlobalUnlock (hHeap);
  166.    GlobalFree (hHeap);
  167.    hHeap = NULL;
  168.    hpBase = NULL;
  169.    nFreeUsed = 0;
  170.    nHeapUsed = 0;
  171.    nNodes = 0;
  172.    return (IDE_OK);
  173. }
  174.  
  175. /***AllocMemMan***********************************************************
  176. ** Program:    Memory Manager
  177. ** File:       Memman.c
  178. ** Funktion:   AllocMemMan dynamically gets a piece of memory from the heap
  179. **             and returns a FAR pointer to it
  180. ** Return:     Pointer to object, NULL if error
  181. ** Author:     hb
  182. ** Date:       12.6.92
  183. ****************************************************************************/
  184. void far *AllocMemMan (long lSize)
  185. {
  186.    int      i,
  187.             nIndex,
  188.             nError;
  189.    void far *lpReturn;
  190.  
  191. /* Init **/
  192.    lpReturn = NULL;
  193. /* if size == 0 return error **/
  194.    if (lSize == 0L)
  195.       return (lpReturn);
  196. /* do we have a free heapnode ? **/
  197.    nIndex = GetFreeHeapIndex ();
  198. /* search for block large enough for the request **/
  199.    for (i=0;nIndex != nNodes && i<nFreeUsed;i++)
  200.    {
  201.       if (FreeNodes[i].lSize >= lSize)
  202.       {
  203.          lpReturn = GetPointer (FreeNodes[i].lOffset);
  204. /******* create entry in heapnodes **/
  205.          HeapNodes[nIndex].lSize = lSize;
  206.          HeapNodes[nIndex].lOffset = FreeNodes[i].lOffset;
  207. /******* split node in freenodes **/
  208.          FreeNodes[i].lSize -= lSize;
  209.          FreeNodes[i].lOffset += lSize;
  210.          if (FreeNodes[i].lSize == 0L)
  211.             FreeNodes[i].lOffset = 0L;
  212.          break;
  213.       }
  214.    }
  215. /* no room for the request, try to reorganize heap to satisfy the request **/
  216.    if (lpReturn == NULL)
  217.    {
  218.       nError = MeltFreeList ();
  219. /**** try again **/
  220.       for (i=0;nError == IDE_OK && nIndex != nNodes && i<nFreeUsed;i++)
  221.       {
  222.          if (FreeNodes[i].lSize >= lSize)
  223.          {
  224.             lpReturn = GetPointer (FreeNodes[i].lOffset);
  225.             HeapNodes[nIndex].lSize = lSize;
  226.             HeapNodes[nIndex].lOffset = FreeNodes[i].lOffset;
  227.             FreeNodes[i].lSize -= lSize;
  228.             FreeNodes[i].lOffset += lSize;
  229.             if (FreeNodes[i].lSize == 0L)
  230.                FreeNodes[i].lOffset = 0L;
  231.             break;
  232.          }
  233.       }
  234.    }
  235.    return (lpReturn);
  236. }
  237.  
  238. /***ReAllocMem***********************************************************
  239. ** Program:    Memory Manager
  240. ** File:       Memman.c
  241. ** Funktion:   ReAllocMem changes size of allocated previously allocated objct
  242. **             - if size == 0, free node
  243. **             - if there is no adjacent node to satisfy request, move block to